package com.harmony.pilot.knowledge.service;

import com.harmony.pilot.knowledge.entity.CodeSnippet;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * Prompt构建服务
 * 为LLM构建包含代码上下文的Prompt
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PromptBuilderService {
    
    @Value("${knowledge.rag.max-context-tokens:4000}")
    private int maxContextTokens;
    
    /**
     * 构建代码续写的Prompt
     */
    public String buildContinuationPrompt(String prefix, String context, List<CodeSnippet> snippets) {
        StringBuilder prompt = new StringBuilder();
        
        prompt.append("# OpenHarmony代码续写任务\n\n");
        prompt.append("## 当前代码上下文\n\n");
        prompt.append("```cpp\n");
        prompt.append(context);
        prompt.append("\n```\n\n");
        
        prompt.append("## 已输入代码\n\n");
        prompt.append("```cpp\n");
        prompt.append(prefix);
        prompt.append("\n```\n\n");
        
        if (!snippets.isEmpty()) {
            prompt.append("## 相关代码示例\n\n");
            
            int tokenCount = 0;
            int maxSnippets = Math.min(5, snippets.size());
            
            for (int i = 0; i < maxSnippets && tokenCount < maxContextTokens; i++) {
                CodeSnippet snippet = snippets.get(i);
                
                prompt.append("### 示例 ").append(i + 1).append(": ");
                prompt.append(snippet.getSummary()).append("\n");
                prompt.append("文件: `").append(snippet.getRelativePath()).append("`\n\n");
                prompt.append("```cpp\n");
                prompt.append(snippet.getContent());
                prompt.append("\n```\n\n");
                
                // 粗略估算token数（1个字符约等于1个token）
                tokenCount += snippet.getContent().length();
            }
        }
        
        prompt.append("## 任务\n\n");
        prompt.append("请根据上述代码上下文和示例，续写代码。要求：\n");
        prompt.append("1. 遵循OpenHarmony编码规范\n");
        prompt.append("2. 保持与上下文的一致性\n");
        prompt.append("3. 添加必要的注释\n");
        prompt.append("4. 处理边界情况和错误\n\n");
        prompt.append("请直接输出续写的代码，不需要解释：\n\n");
        
        return prompt.toString();
    }
    
    /**
     * 构建代码生成的Prompt
     */
    public String buildGenerationPrompt(String description, String context, List<CodeSnippet> snippets) {
        StringBuilder prompt = new StringBuilder();
        
        prompt.append("# OpenHarmony代码生成任务\n\n");
        prompt.append("## 需求描述\n\n");
        prompt.append(description).append("\n\n");
        
        if (context != null && !context.isEmpty()) {
            prompt.append("## 当前文件上下文\n\n");
            prompt.append("```cpp\n");
            prompt.append(context);
            prompt.append("\n```\n\n");
        }
        
        if (!snippets.isEmpty()) {
            prompt.append("## 参考代码示例\n\n");
            
            for (int i = 0; i < Math.min(3, snippets.size()); i++) {
                CodeSnippet snippet = snippets.get(i);
                
                prompt.append("### 示例 ").append(i + 1).append(": ");
                prompt.append(snippet.getSummary()).append("\n");
                prompt.append("文件: `").append(snippet.getRelativePath()).append("`\n\n");
                prompt.append("```cpp\n");
                prompt.append(snippet.getContent());
                prompt.append("\n```\n\n");
            }
        }
        
        prompt.append("## 任务\n\n");
        prompt.append("请根据需求描述和参考示例，生成OpenHarmony C++代码。要求：\n");
        prompt.append("1. 遵循OpenHarmony编码规范\n");
        prompt.append("2. 包含必要的头文件引用\n");
        prompt.append("3. 添加详细的注释和文档\n");
        prompt.append("4. 考虑错误处理和边界情况\n\n");
        
        return prompt.toString();
    }
    
    /**
     * 构建单元测试生成的Prompt
     */
    public String buildTestGenerationPrompt(String functionCode, List<CodeSnippet> testExamples) {
        StringBuilder prompt = new StringBuilder();
        
        prompt.append("# OpenHarmony单元测试生成任务\n\n");
        prompt.append("## 目标函数\n\n");
        prompt.append("```cpp\n");
        prompt.append(functionCode);
        prompt.append("\n```\n\n");
        
        if (!testExamples.isEmpty()) {
            prompt.append("## 测试示例参考\n\n");
            
            for (int i = 0; i < Math.min(3, testExamples.size()); i++) {
                CodeSnippet example = testExamples.get(i);
                
                prompt.append("### 示例 ").append(i + 1).append("\n");
                prompt.append("文件: `").append(example.getRelativePath()).append("`\n\n");
                prompt.append("```cpp\n");
                prompt.append(example.getContent());
                prompt.append("\n```\n\n");
            }
        }
        
        prompt.append("## 任务\n\n");
        prompt.append("请为上述函数生成完整的Google Test单元测试。要求：\n");
        prompt.append("1. 使用TEST_F或TEST宏\n");
        prompt.append("2. 包含正常情况、边界情况和异常情况的测试\n");
        prompt.append("3. 使用EXPECT_EQ, EXPECT_TRUE等断言\n");
        prompt.append("4. 添加清晰的测试注释\n\n");
        
        return prompt.toString();
    }
    
    /**
     * 构建Fuzzer生成的Prompt
     */
    public String buildFuzzerGenerationPrompt(String functionCode, List<CodeSnippet> fuzzerExamples) {
        StringBuilder prompt = new StringBuilder();
        
        prompt.append("# OpenHarmony Fuzzer测试生成任务\n\n");
        prompt.append("## 目标函数\n\n");
        prompt.append("```cpp\n");
        prompt.append(functionCode);
        prompt.append("\n```\n\n");
        
        if (!fuzzerExamples.isEmpty()) {
            prompt.append("## Fuzzer示例参考\n\n");
            
            for (int i = 0; i < Math.min(3, fuzzerExamples.size()); i++) {
                CodeSnippet example = fuzzerExamples.get(i);
                
                prompt.append("### 示例 ").append(i + 1).append("\n");
                prompt.append("文件: `").append(example.getRelativePath()).append("`\n\n");
                prompt.append("```cpp\n");
                prompt.append(example.getContent());
                prompt.append("\n```\n\n");
            }
        }
        
        prompt.append("## 任务\n\n");
        prompt.append("请为上述函数生成libFuzzer测试代码。要求：\n");
        prompt.append("1. 实现LLVMFuzzerTestOneInput函数\n");
        prompt.append("2. 正确使用data和size参数\n");
        prompt.append("3. 添加输入数据的验证和边界检查\n");
        prompt.append("4. 包含必要的头文件\n\n");
        
        return prompt.toString();
    }
    
    /**
     * 构建代码解释的Prompt
     */
    public String buildExplanationPrompt(String code, List<CodeSnippet> relatedCode) {
        StringBuilder prompt = new StringBuilder();
        
        prompt.append("# OpenHarmony代码解释任务\n\n");
        prompt.append("## 待解释代码\n\n");
        prompt.append("```cpp\n");
        prompt.append(code);
        prompt.append("\n```\n\n");
        
        if (!relatedCode.isEmpty()) {
            prompt.append("## 相关上下文\n\n");
            
            for (int i = 0; i < Math.min(2, relatedCode.size()); i++) {
                CodeSnippet snippet = relatedCode.get(i);
                
                prompt.append("### ").append(snippet.getSummary()).append("\n");
                prompt.append("```cpp\n");
                prompt.append(snippet.getContent().substring(0, Math.min(500, snippet.getContent().length())));
                prompt.append("\n...\n```\n\n");
            }
        }
        
        prompt.append("## 任务\n\n");
        prompt.append("请详细解释上述OpenHarmony代码的功能、实现原理和注意事项。\n\n");
        
        return prompt.toString();
    }
    
    /**
     * 估算token数量（简单实现）
     */
    public int estimateTokens(String text) {
        // 简单估算：英文约4个字符=1个token，中文约1.5个字符=1个token
        int chineseChars = text.replaceAll("[^\u4e00-\u9fa5]", "").length();
        int otherChars = text.length() - chineseChars;
        
        return (int) (chineseChars / 1.5 + otherChars / 4.0);
    }
    
    /**
     * 截断文本以适应token限制
     */
    public String truncateToTokenLimit(String text, int maxTokens) {
        int estimatedTokens = estimateTokens(text);
        
        if (estimatedTokens <= maxTokens) {
            return text;
        }
        
        // 按比例截断
        double ratio = (double) maxTokens / estimatedTokens;
        int targetLength = (int) (text.length() * ratio * 0.9); // 留10%余量
        
        if (targetLength < text.length()) {
            return text.substring(0, targetLength) + "\n... (truncated)";
        }
        
        return text;
    }
}

